/**
 * Copyright (c) 2015-2030 by Beijing Yanlight Co., Ltd.
 * All rights reserved.
 */
package com.yanlight.util;

import java.io.StringReader;
import java.util.StringTokenizer;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * 
 * @author haolw
 * @time 2018/09/14
 */
public abstract class DocumentUtil {

	public static Document parseText(String text) throws DocumentException {
		try {
			SAXReader reader = createSAXReader();
			String encoding = getEncoding(text);
			InputSource source = new InputSource(new StringReader(text));
			source.setEncoding(encoding);
			Document result = reader.read(source);
			if (result.getXMLEncoding() == null) {
				result.setXMLEncoding(encoding);
			}
			return result;
		} catch (Exception e) {
			if (!e.getMessage().contains("http://apache.org/xml/features/disallow-doctype-decl")) {
				throw e;
			} else {
				return DocumentHelper.createDocument(DocumentHelper.createElement("error"));
			}
		}
	}

	private static String getEncoding(String text) {
		String result = null;
		String xml = text.trim();
		if (xml.startsWith("<?xml")) {
			int end = xml.indexOf("?>");
			String sub = xml.substring(0, end);
			StringTokenizer tokens = new StringTokenizer(sub, " =\"\'");
			while (tokens.hasMoreTokens()) {
				String token = tokens.nextToken();
				if ("encoding".equals(token)) {
					if (tokens.hasMoreTokens()) {
						result = tokens.nextToken();
					}
					break;
				}
			}
		}
		return result;
	}

	private static SAXReader createSAXReader() throws DocumentException {
		SAXReader reader = new SAXReader();
		try {
			String feature = "http://apache.org/xml/features/disallow-doctype-decl";
			reader.setFeature(feature, true);
			feature = "http://xml.org/sax/features/external-general-entities";
			reader.setFeature(feature, false);
			feature = "http://xml.org/sax/features/external-parameter-entities";
			reader.setFeature(feature, false);
			feature = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
			reader.setFeature(feature, false);
		} catch (SAXException e) {
			throw new DocumentException(e);
		}
		return reader;
	}

}
